package king.dominic.jcamera;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.YuvImage;
import android.view.Display;
import android.view.WindowManager;

import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;

/**
 * Created by DominicKing on 2018/1/22.
 */

class Utils {
    static final int ORIENTATION_PORTRAIT = 0;
    static final int ORIENTATION_LANDSCAPE = 1;

    static int getOrientation(Context context) {
        Point screenResolution = getScreenResolution(context);
        return screenResolution.x > screenResolution.y ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
    }

    static Point getScreenResolution(Context context) {
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        Point screenResolution = new Point();
        if (android.os.Build.VERSION.SDK_INT >= 13) {
            display.getSize(screenResolution);
        } else {
            screenResolution.set(display.getWidth(), display.getHeight());
        }
        return screenResolution;
    }

    static Bitmap decodeYuvByteArray(byte[] data, int format, int width, int height) {
        return decodeYuvByteArray(data, format, width, height, 0, 0);
    }

    private static Bitmap decodeYuvByteArray(byte[] data, int format, int width, int height, int maxWidth, int maxHeight) {
        return decodeYuvByteArray(data, format, width, height, maxWidth, maxHeight, null);
    }

    private static Bitmap decodeYuvByteArray(byte[] data, int format, int width, int height, int maxWidth, int maxHeight, Rect bounds) {
        return decodeYuvByteArray(data, format, width, height, maxWidth, maxHeight, Bitmap.Config.ARGB_8888, bounds);
    }

    private static Bitmap decodeYuvByteArray(byte[] data, int format, int width, int height, int maxWidth, int maxHeight, Bitmap.Config toFormat, Rect bounds) {
        YuvImage yuvImage = new YuvImage(data, format, width, height, null);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        yuvImage.compressToJpeg(new Rect(0, 0, width, height), 100, baos);
        byte[] jpegData = baos.toByteArray();

        closeStreamAutoCatch(baos);

        BitmapFactory.Options opt = new BitmapFactory.Options();
        opt.inPreferredConfig = toFormat;

        if (maxWidth <= 0 && maxHeight <= 0)
            return BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, opt);

        opt.inJustDecodeBounds = true;
        BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, opt);
        opt.inSampleSize = maxWidth <= 0 ? opt.outHeight / maxHeight : (maxHeight <= 0 ? opt.outWidth / maxWidth : Math.max(opt.outHeight / maxHeight, opt.outWidth / maxWidth));
        opt.inSampleSize = opt.inSampleSize <= 0 ? 1 : opt.inSampleSize;

        opt.inJustDecodeBounds = false;

        if (bounds == null || bounds.width() <= 0 || bounds.height() <= 0)
            return BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, opt);
        Bitmap src = BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, opt);
        float scale = 1f * width / src.getWidth();
        Bitmap bitmap = crop(src, new Rect((int) (bounds.left / scale), (int) (bounds.top / scale), (int) (bounds.right / scale), (int) (bounds.bottom / scale)));
        src.recycle();
        return bitmap;
    }

    private static Bitmap crop(Bitmap bitmap, Rect bounds) {
        return crop(bitmap, (int) bounds.left, (int) bounds.top, (int) bounds.right, (int) bounds.bottom);
    }

    private static Bitmap crop(Bitmap bitmap, int l, int t, int r, int b) {
        return Bitmap.createBitmap(bitmap, l, t, r - l, b - t);
    }

    private static void closeStreamAutoCatch(Closeable stream) {
        try {
            closeStream(stream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void closeStream(Closeable stream) throws IOException {
        if (stream == null) return;
        stream.close();
    }

}
